from django.shortcuts import render,redirect
from django.views import View
from django.urls import reverse
from django_redis import get_redis_connection
from django.http.response import JsonResponse
from django.db import transaction
from django.db.models import F
from .models import *
from datetime import *
from apps.user.models import Address
from apps.goods.models import GoodsSKU
from alipay import AliPay
from django.conf import settings
import os
# Create your views here.

#cart/place
class OrderPlaceView(View):
    """订单提交"""
    def post(self,request):
        #判断用户是否登陆
        user=request.user
        if not user.is_authenticated:
            return redirect(reverse("user:login"))

        #接收数据
        sku_ids=request.POST.getlist("sku_ids")
        #print(sku_ids)

        if not sku_ids:
            return redirect(reverse("cart:index"))

        conn=get_redis_connection("default")
        cart_key="cart_%d" % user.id

        total_count=0
        total_price=0
        skus=[]
        #遍历商品
        for sku_id in sku_ids:
            sku=GoodsSKU.objects.get(id=sku_id)
            count=conn.hget(cart_key,sku_id)
            count=int(count)
            amount=sku.price*count
            sku.count=count
            sku.amount=amount
            skus.append(sku)
            total_count+=count
            total_price+=amount

        #运费
        transit_price=10
        pay_price=transit_price+total_price

        #查询用户的收获地址和订单
        addrs=Address.objects.filter(user=user)
        print(addrs)
        sku_ids=",".join(sku_ids)
        content={
            "addrs":addrs,
            "skus":skus,
            "total_price":total_price,
            "total_count":total_count,
            "transit_price":transit_price,
            "pay_price":pay_price,
            "sku_ids":sku_ids
        }
        return render(request,"place_order.html",content)

class OrderCommitView(View):
    """生成订单"""
    @transaction.atomic
    def post(self,request):
        #接收数据
        # 判断用户是否登陆
        user = request.user
        if not user.is_authenticated:
            return redirect(reverse("user:login"))

        sku_ids=request.POST.get("sku_ids")
        sku_ids=sku_ids.split(",")
        addr_id=request.POST.get("addr_id")
        pay_style=request.POST.get("pay_style")

        #校检数据
        if not all([sku_ids,addr_id,pay_style]):
            return JsonResponse({
                "res":0,
                "errmsg":"数据不完整"
            })

        try:
            addr=Address.objects.get(id=addr_id)
        except Address.DoesNotExist:
            return JsonResponse({
                "res": 1,
                "errmsg": "地址不存在"
            })

        if pay_style not in OrderInfo.PAY_METHOD.keys():
            return JsonResponse({
                "res": 2,
                "errmsg": "支付方式非法"
            })

        #业务逻辑
        #todo:添加一条数据到order_info表中
        transit_price=10
        total_count=0
        total_price=0
        order_id=datetime.now().strftime("%Y%m%d%H%M%S")+str(user.id)
        #设置一个事物保存点
        sid=transaction.savepoint()
        try:
            order=OrderInfo.objects.create(
                order_id=order_id,pay_method=pay_style,
                addr=addr,user=user,
                transit_price=transit_price,total_count=total_count,
                total_price=total_price
            )

            conn=get_redis_connection("default")
            cart_key="cart_%d" % user.id

            #todo:遍历商品,添加数据到order_goods表中
            for sku_id in sku_ids:
                try:
                    # select * from df_goods_sku where id=sku_id for update;(悲观锁)
                    #sku=GoodsSKU.objects.select_for_update().get(id=sku_id)
                    sku = GoodsSKU.objects.get(id=sku_id)
                    #记录原始库存
                    orign_stock=sku.stock
                except GoodsSKU.DoesNotExist:
                    #事物回滚
                    transaction.savepoint_rollback(sid)
                    return JsonResponse({
                        "res":3,
                        "errmsg":"商品不存在"
                    })
                count=conn.hget(cart_key,sku_id)
                count=int(count)
                #判断库存
                if count>sku.stock:
                    return JsonResponse({
                        "res":4,
                        "errmsg":"库存不足"
                    })

                import time
                time.sleep(10)

                total_count += count
                total_price += sku.price * count
                # 更新商品销量和库存

                # 乐观锁
                res = GoodsSKU.objects.filter(id=sku_id, stock=orign_stock).update(
                    stock=F("stock") - count, sales=F("sales") + count
                )
                if res == 0:
                    # 事物回滚
                    transaction.savepoint_rollback(sid)
                    return JsonResponse({
                        'res': 7,
                        'errmsg': '下单失败'
                    })

                OrderGoods.objects.create(
                    count=count,price=sku.price,
                    order=order,sku=sku
                )


                #sku.stock-=count
                #sku.sales+=count
                #sku.save()

            #保存订单总价和总数
            order.total_count=total_count
            order.total_price=total_price
            order.save()
        except Exception as e:
            # 事物回滚
            transaction.savepoint_rollback(sid)
            return JsonResponse({
                'res': 6,
                'errmsg': '下单失败'
            })

        conn.hdel(cart_key,*sku_ids)

        #应答
        return JsonResponse({
                    "res":5,
                    "errmsg":"订单创建成功"
                })

class OrderPayView(View):
    """订单付款"""
    def post(self,request):
        '''订单支付'''
        # 用户是否登录
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '用户未登录'})

        # 接收参数
        order_id = request.POST.get('order_id')

        # 校验参数
        if not order_id:
            return JsonResponse({'res': 1, 'errmsg': '无效的订单id'})

        try:
            order = OrderInfo.objects.get(order_id=order_id,
                                          user=user,
                                          pay_method=3,
                                          order_status=1)
        except OrderInfo.DoesNotExist:
            return JsonResponse({'res': 2, 'errmsg': '订单错误'})

        # 业务处理:使用python sdk调用支付宝的支付接口
        # 初始化
        alipay = AliPay(
            appid="2016092000556038",  # 应用id
            app_notify_url=None,  # 默认回调url
            app_private_key_path=os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem'),
            alipay_public_key_path=os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem'),
            # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=True  # 默认False
        )

        # 调用支付接口
        # 电脑网站支付，需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string
        total_pay = order.total_price + order.transit_price  # Decimal
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,  # 订单id
            total_amount=str(total_pay),  # 支付总金额
            subject='天天生鲜%s' % order_id,
            return_url=None,
            notify_url=None  # 可选, 不填则使用默认notify url
        )

        # 返回应答
        pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string
        return JsonResponse({'res': 3, 'pay_url': pay_url})

# ajax post
# 前端传递的参数:订单id(order_id)
# /order/check
class CheckPayView(View):
    '''查看订单支付的结果'''
    def post(self, request):
        '''查询支付结果'''
        # 用户是否登录
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '用户未登录'})

        # 接收参数
        order_id = request.POST.get('order_id')

        # 校验参数
        if not order_id:
            return JsonResponse({'res': 1, 'errmsg': '无效的订单id'})

        try:
            order = OrderInfo.objects.get(order_id=order_id,
                                          user=user,
                                          pay_method=3,
                                          order_status=1)
        except OrderInfo.DoesNotExist:
            return JsonResponse({'res': 2, 'errmsg': '订单错误'})

        # 业务处理:使用python sdk调用支付宝的支付接口
        # 初始化
        alipay = AliPay(
            appid="2016092000556038",  # 应用id
            app_notify_url=None,  # 默认回调url
            app_private_key_path=os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem'),
            alipay_public_key_path=os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem'),
            # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=True  # 默认False
        )

        # 调用支付宝的交易查询接口
        while True:
            response = alipay.api_alipay_trade_query(order_id)

            # response = {
            #         "trade_no": "2017032121001004070200176844", # 支付宝交易号
            #         "code": "10000", # 接口调用是否成功
            #         "invoice_amount": "20.00",
            #         "open_id": "20880072506750308812798160715407",
            #         "fund_bill_list": [
            #             {
            #                 "amount": "20.00",
            #                 "fund_channel": "ALIPAYACCOUNT"
            #             }
            #         ],
            #         "buyer_logon_id": "csq***@sandbox.com",
            #         "send_pay_date": "2017-03-21 13:29:17",
            #         "receipt_amount": "20.00",
            #         "out_trade_no": "out_trade_no15",
            #         "buyer_pay_amount": "20.00",
            #         "buyer_user_id": "2088102169481075",
            #         "msg": "Success",
            #         "point_amount": "0.00",
            #         "trade_status": "TRADE_SUCCESS", # 支付结果
            #         "total_amount": "20.00"
            # }

            code = response.get('code')

            if code == '10000' and response.get('trade_status') == 'TRADE_SUCCESS':
                # 支付成功
                # 获取支付宝交易号
                trade_no = response.get('trade_no')
                # 更新订单状态
                order.trade_no = trade_no
                order.order_status = 4  # 待评价
                order.save()
                # 返回结果
                return JsonResponse({'res': 3, 'message': '支付成功'})
            elif code == '40004' or (code == '10000' and response.get('trade_status') == 'WAIT_BUYER_PAY'):
                # 等待买家付款
                # 业务处理失败，可能一会就会成功
                import time
                time.sleep(5)
                continue
            else:
                # 支付出错
                print(code)
                return JsonResponse({'res': 4, 'errmsg': '支付失败'})

class OrderCommentView(View):
    """订单评论"""
    def get(self,request,order_id):
        # 用户是否登录
        user = request.user
        if not user.is_authenticated:
            return redirect(reverse("user:login"))

        # 校验参数
        try:
            order=OrderInfo.objects.get(order_id=order_id)
        except OrderInfo.DoesNotExist:
            return JsonResponse({'res': 1, 'errmsg': '订单号不存在'})

        order_goods=OrderGoods.objects.filter(order_id=order_id)
        for order_good in order_goods:
            amount=order_good.price*order_good.count
            order_good.amount=amount
        order.order_skus=order_goods
        content={
            "order":order,
        }

        return render(request,"order_comment.html",content)

    def post(self,request,order_id):
        # 用户是否登录
        user = request.user
        if not user.is_authenticated:
            return redirect(reverse("user:login"))

        #接收数据
        total_count=request.POST.get("total_count")

        #校检数据
        if not all([total_count,order_id]):
            return JsonResponse({'res': 1, 'errmsg': '数据不完整'})

        for i in range(1,int(total_count)+1):
            sku_id=request.POST.get("sku_%d" % i)
            comment=request.POST.get("content_%d" % i," ")
            try:
                sku=GoodsSKU.objects.get(id=sku_id)
                order_good=OrderGoods.objects.get(order_id=order_id,sku=sku)
            except Exception as e:
                continue
            order_good.comment=comment
            order_good.save()

        OrderInfo.objects.filter(order_id=order_id).update(order_status=5)

        return redirect(reverse("goods:index"))
